package cate.game.role.res.spicecall;

import cate.common.table.activity.spiceup.row.SpiceUpTypeRow;
import cate.common.table.d.*;
import cate.common.table.item.spice.row.SpiceBaseRow;
import cate.common.table.item.spice.row.SpiceCallBaseRow;
import cate.common.table.item.spice.row.SpiceCallRewardRow;
import cate.common.table.role.vip.RoleVipRow;
import cate.common.util.GameResult;
import cate.game.activity.crossrank.po.CrossRankActivity;
import cate.game.chat.ChatContentParam;
import cate.game.client.msg.MergeMsgSender;
import cate.game.framework.ISilenceSpanable;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.role.FuncOpenChecker;
import cate.game.role.Role;
import cate.game.role.res.spicecall.msg.SpiceCallBatchExeResp;
import cate.game.role.res.spicecall.msg.SpiceCallDataResp;
import cate.game.role.res.spicecall.msg.SpiceCallTempItemsResp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

@NoteClass(value = "星格祈祷")
public class SpiceCall extends FuncOpenChecker implements ISilenceSpanable {
    @NoteField(value = "今日免费祈祷次数")
    public int freeCallTime;

    @NoteField(value = "今日开运次数")
    public int goodLuckTime;

    @NoteField(value = "Map<祈祷雕像的id，总祈祷次数>")
    @JsonIgnore
    public Map<Integer, Integer> callHistory;

    @NoteField(value = "祈祷记录")
    public List<Integer> logs;

    @NoteField(value = "当前所在雕像")
    public int pos;

    @NoteField(value = "临时背包道具")
    public List<Integer> tempItems;

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (callHistory == null) {
            callHistory = new HashMap<>();
        }
        if (logs == null) {
            logs = new ArrayList<>();
        }
        if (tempItems == null) {
            tempItems = new ArrayList<>();
        }
        if (pos == 0) {
            pos = 1;
        }
    }

    @Override
    public int getFuncId() {
        return GDFunc.SPICE_CALL;
    }

    @Override
    public void onAfterOpen() {
        noticeUpdate();
    }

    private EcResult<MixResItem> itemConsume(SpiceCallBaseRow baseRow, MergeMsgSender sender) {
        if (baseRow == null) {
            return new EcResult<MixResItem>().fail("星格研制数据有误");
        }
        MixRes mixRes = new MixRes(baseRow.consumeStr);
        return mixRes.consume(role, null, sender);
    }

    /**
     * 一键祈祷
     */
    public GameResult<Void> batchCall() {
        GameResult<Void> r = new GameResult<>();
        int emptyGrid = GDSpiceCall.TEMP_BAG_INIT_SIZE - tempItems.size();
        if (emptyGrid <= 0) {
            return r.fail(310207, Math.abs(emptyGrid));
        }
        EcResult<List<Integer>> callRes = callExe(emptyGrid, false, false);
        if (!callRes.ok()) {
            return r.fail(callRes.message);
        }
        role.sendNow(new SpiceCallBatchExeResp(callRes.data));
        noticeUpdate();
        return r.success("批量研制成功");
    }

    public GameResult<Void> callExe(boolean violent, boolean autoPut) {
        GameResult<Void> r = new GameResult<>();
        SpiceCallBaseRow baseRow = systemOrActivityBaseRow();
        if (baseRow == null) {
            return r.fail("星点不存在");
        }
        int times = violent ? 100 : 1;
        int remain;
        if (violent) {
            remain = role.getBag().spice.gridEmpty();
        } else {
            remain = GDSpiceCall.TEMP_BAG_INIT_SIZE - tempItems.size();
        }
        if (remain < times) {
            if (violent) {
                return r.fail(310206, times - remain);
            } else {
                return r.fail(310207, times - remain);
            }
        }
        EcResult<List<Integer>> callRes = callExe(times, autoPut, violent);
        if (!callRes.ok()) {
            return r.fail(callRes.message);
        }
        role.sendNow(new SpiceCallBatchExeResp(callRes.data));
        noticeUpdate();
        return r;
    }

    private SpiceCallBaseRow systemOrActivityBaseRow(int pos) {
        if (getActivity() != null) {
            return getActivityTypeRow(pos);
        }
        return role.getGame().table.spice.callBase.get(pos);
    }

    @JsonIgnore
    private CrossRankActivity getActivity() {
        return role.getActivity().getEnableActivitySingle(GDFunc.Help.CROSS_SPICE_CALL_RANK);
    }

    @JsonIgnore
    public SpiceUpTypeRow getActivityTypeRow(int pos) {
        return game().table.spiceUp.type.get(pos);
    }

    private SpiceCallBaseRow systemOrActivityBaseRow() {
        if (getActivity() != null) {
            return getActivityTypeRow(this.pos);
        }
        return role.getGame().table.spice.callBase.get(this.pos);
    }

    private GameResult<List<Integer>> callExe(int times, boolean autoPut, boolean violent) {
        GameResult<List<Integer>> r = new GameResult<>();
        //固定消耗的召唤次数
        int freeTimes = availableFreeTimes(times);
        List<Integer> rewardList = new ArrayList<>();
        // 判断是否抽到了稀有道具
        boolean gotRare = false;
        // 通过检测开始祈祷了
        MergeMsgSender sender = new MergeMsgSender();
        String errMsg = null;
        int openDay = role.getGame().getOpenDay();
        MixRes reward = new MixRes();
        for (int i = 0, j = 0; i < times; i++, j++) {
            SpiceCallBaseRow baseRow = systemOrActivityBaseRow();
            //如果超过了免费次数
            if (j >= freeTimes) {
                //先扣道具
                EcResult<MixResItem> itemConsume = itemConsume(baseRow, sender);
                if (!itemConsume.ok()) {
                    role.getGame().notice.tipResItem(role, itemConsume.data);
                    errMsg = itemConsume.message;
                    break;
                }
            }
            EcResult<Integer> callRes = singleCallExe(openDay);
            // 如果本次祈祷成功 同时之前没抽到稀有道具
            if (callRes.ok()) {
                Integer rewardTid = callRes.data;
                rewardList.add(rewardTid);
                SpiceCallRewardRow rewardRow = systemOrActivityRewardRow(rewardTid);
                if (!gotRare) {
                    gotRare = rewardRow.record;
                }
                if (violent) {
                    reward.addList(new MixRes(rewardRow.rewardStr));
                } else {
                    tempItems.add(rewardRow.id);
                    if (autoPut && tempItems.size() >= GDSpiceCall.TEMP_BAG_INIT_SIZE && role.getBag().spice.gridEmpty() >= tempItems.size()) {
                        Iterator<Integer> iter = tempItems.iterator();
                        while (iter.hasNext()) {
                            Integer rewardId = iter.next();
                            SpiceCallRewardRow row = systemOrActivityRewardRow(rewardId);
                            if (row != null) {
                                reward.addList(new MixRes(row.rewardStr));
                                iter.remove();
                            }
                        }
                    }
                }
                lampNiubi(rewardRow);
                if (this.pos == GDSpiceCall.NIUBI_POS && !violent) {
                    break;
                }
            } else {
                errMsg = callRes.message;
            }
        }
        if (rewardList.isEmpty()) {
            if (StringUtils.isNotBlank(errMsg)) {
                return r.fail(errMsg);
            }
            return r.fail("占星资源不足");
        }
        if (!reward.isEmpty()) {
            reward.add(role, true, 0, sender);
            doRewardTask(reward);
        }
        sender.send(role, true);
        if (violent) {
            role.getGame().notice.dialogReward(role, reward);
        }
        if (gotRare) {
            role.getGame().res.spiceCall.noticeUpdate(role);
        }
        r.data = rewardList;
        role.getHistory().action.spiceCall(rewardList.size());
        return r;
    }

    private void lampNiubi(SpiceCallRewardRow rewardRow) {
        MixResItem reward = new MixRes(rewardRow.rewardStr).items.get(0);
        if(rewardRow.record && reward.type == GDObj.Type.SPICE){
            List<ChatContentParam> params = new ArrayList<>();
            params.add(ChatContentParam.c(role.getBase().name));
            params.add(ChatContentParam.c(ChatContentParam.TYPE_SPICE_ID, reward));
            role.getGame().notice.lampOnline(role, GDNotice.TextId.SPICE_CALL, params);
        }
    }

    private void doRewardTask(MixRes reward) {
        int num = 0;
        for (MixResItem item : reward.items) {
            if (item.type == GDObj.Type.SPICE) {
                SpiceBaseRow baseRow = role.getGame().table.spice.base.get(item.tid);
                if (baseRow != null) {
                    num += item.num;
                }
            }
        }
        if (num > 0) {
            role.getHistory().action.spiceGet(num);
        }
    }

    /**
     * 领取临时背包奖励
     *
     * @return r
     */
    @JsonIgnore
    public GameResult<Void> getReward() {
        GameResult<Void> r = new GameResult<>();
        MixRes reward = new MixRes();
        boolean gotAvaible = false;
        int remain = role.getBag().spice.gridEmpty();
        if (remain < tempItems.size()) {
            return r.fail(310208, tempItems.size() - remain);
        }
        for (Integer rewardId : tempItems) {
            SpiceCallRewardRow row = systemOrActivityRewardRow(rewardId);
            if (row != null) {
                gotAvaible = true;
                reward.addList(new MixRes(row.rewardStr));
            }
        }
        if (!gotAvaible) {
            return r.fail("没有可以领取的奖励");
        }
        MergeMsgSender sender = new MergeMsgSender();
        r = reward.add(role, false, 0, sender);
        if (!r.ok()) {
            return r;
        }
        sender.send(role, true);
        tempItems.clear();
        role.sendNow(new SpiceCallTempItemsResp(tempItems));
        doRewardTask(reward);
        return r.success();
    }

    /**
     * 领取临时背包奖励
     *
     * @return r
     */
    @JsonIgnore
    public GameResult<Void> getOneReward(int index) {
        GameResult<Void> r = new GameResult<>();
        if (index < 0 || index >= tempItems.size()) {
            return r.fail("没有这个星格噢");
        }
        int remain = role.getBag().spice.gridEmpty();
        if (remain < 1) {
            return r.fail(310208, 1);
        }
        MixRes reward = new MixRes();
        int rewardId = tempItems.get(index);
        SpiceCallRewardRow row = systemOrActivityRewardRow(rewardId);
        if (row != null) {
            reward.addList(new MixRes(row.rewardStr));
        }
        r = reward.add(role, false);
        if (!r.ok()) {
            return r;
        }
        tempItems.remove(index);
        role.sendNow(new SpiceCallTempItemsResp(tempItems));
        return r.success();
    }

    /**
     * 祈祷一次
     *
     * @return 祈祷抽到的奖励id
     */
    private GameResult<Integer> singleCallExe(int openday) {
        GameResult<Integer> r = new GameResult<>();
        SpiceCallBaseRow baseRow = systemOrActivityBaseRow();
        Integer historyNum = callHistory.get(this.pos);
        if (historyNum == null) {
            historyNum = 0;
        }
        historyNum++;
        // 获取本次祈祷进的奖励分组
        int groupId = getCallGroup(openday);
        SpiceCallRewardRow rewardRow = randomSystemOrActivityReward(groupId);
        if (rewardRow == null) {
            return r.fail(80160, "研制奖励配置错误");
        }
        r.data = rewardRow.id;
        addLog(rewardRow.id);
        // 全服记录
        if (rewardRow.record) {
            role.getGame().res.spiceCall.addLog(baseRow.id, role.getBase().name, rewardRow.id);
        }
        // 变更pos
        this.pos = randomPos();
        callHistory.put(baseRow.id, historyNum);
        return r.success();
    }

    private SpiceCallRewardRow randomSystemOrActivityReward(int groupId) {
        if (getActivity() != null) {
            return game().table.spiceUp.weight.randomReward(groupId);
        }
        return role.getGame().table.spice.callReward.randomReward(groupId);
    }

    private SpiceCallRewardRow systemOrActivityRewardRow(int rewardTid) {
        if (getActivity() != null) {
            return game().table.spiceUp.weight.get(rewardTid);
        }
        return role.getGame().table.spice.callReward.get(rewardTid);
    }

    public GameResult<Void> goodLuck(int pos) {
        GameResult<Void> r = new GameResult<>();
        RoleVipRow vip = role.getBase().getVipRow();
        if (vip == null || goodLuckTime >= vip.spiceCallLuckyTimes) {
            return r.fail("点亮福点次数不足");
        }
        if (this.pos == pos) {
            return r.fail("已点亮福点，无需重复操作");
        }
        SpiceCallBaseRow callBaseRow = systemOrActivityBaseRow(pos);
        if (callBaseRow == null) {
            return r.fail("无法点亮此福点");
        }
        if (!niubidexiangzheng() && StringUtils.isNotBlank(callBaseRow.vipConsumeStr)) {
            GameResult<MixResItem> consumeRes = new MixRes(callBaseRow.vipConsumeStr).consume(role);
            if (!consumeRes.ok()) {
                role.getGame().notice.tipResItem(role, consumeRes.data);
                return r.fail(consumeRes);
            }
        }
        this.pos = pos;
        this.goodLuckTime++;
        noticeUpdate();
        role.getHistory().action.spiceCallGoodLuck();
        return r;
    }

    private boolean niubidexiangzheng() {
        return role.getShow().headIcon.isActive(GDSpiceCall.FREE_HEAD_ICON);
    }

    // 玩家日志记录日志
    public void addLog(int rewardId) {
        logs.add(0, rewardId);
        if (logs.size() > GDSpiceCall.LOG_MAX) {
            logs.remove(logs.size() - 1);
        }
    }

    /**
     * 获取当前祈祷的分组
     *
     * @return group
     */
    @JsonIgnore
    private int getCallGroup(int openday) {
        // 常规祈祷时进的分组
        SpiceCallBaseRow baseRow = systemOrActivityBaseRow();
        if (baseRow != null) {
            return baseRow.starGroupList.get().getGroupId().get(0);
        }
        return -1;
    }


    /**
     * 随机下一个进入的雕像
     *
     * @return pos
     */
    @JsonIgnore
    private int randomPos() {
        // 常规祈祷时的随机逻辑
        return role.getGame().table.spice.callBase.randomPos(pos);
    }

    /**
     * 使用免费次数支付
     *
     * @param callTime 次数
     * @return 本次支付成功的次数
     */
    private int availableFreeTimes(int callTime) {
        // 可用的免费次数
        int available = GDSpiceCall.FREE_CALL_TIME - freeCallTime;
        // 本次使用的免费次数
        int payNum = Math.min(available, callTime);
        if (payNum <= 0) {
            return 0;
        }
        // 如果免费次数足够支付
        // 不够的话就尽可能支付
        this.freeCallTime += payNum;
        return payNum;
    }

    @Override
    public void onDaySpan(boolean silence) {
        //要先执行资源找回
        role.getRes().findBack.triggerByFuncId(getFuncId());
        freeCallTime = 0;
        goodLuckTime = 0;
        noticeUpdate();
    }

    public void noticeUpdate() {
        if (isOpen()) {
            role.sendNow(new SpiceCallDataResp(this));
        }
    }
}
